package com.hzw.saas.service.workspace.service;


import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;
import java.util.*;
import javax.annotation.Resource;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.IService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hzw.saas.api.user.IUserRightsService;
import com.hzw.saas.api.user.bo.UserRightsBO;
import com.hzw.saas.api.workspace.IWorkInstanceService;
import com.hzw.saas.api.workspace.IWorkRecordsService;
import com.hzw.saas.api.workspace.bo.WorkInstanceBo;
import com.hzw.saas.api.workspace.bo.WorkRecordsBo;
import com.hzw.saas.common.config.util.PageParam;
import com.hzw.saas.common.util.MapperUtil;
import com.hzw.saas.common.util.SnowFlakeUtil;
import com.hzw.saas.common.util.UnitConvertUtils;
import com.hzw.saas.common.util.enums.TimeUnitEnum;
import com.hzw.saas.service.workspace.mapper.WorkRecordsMapper;
import com.hzw.saas.service.workspace.pojo.model.WorkRecords;
import cn.hutool.core.date.LocalDateTimeUtil;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;

/**

 */
@Service("workRecordsServiceImpl")
@RequiredArgsConstructor
@Slf4j
public class WorkRecordsServiceImpl extends ServiceImpl<WorkRecordsMapper, WorkRecords> implements IWorkRecordsService, IService<WorkRecords> {

    private final IUserRightsService rightsService;
    private final IUserRightsService userRightsService;
    @Resource(name = "workInstanceServiceImpl")
    private IWorkInstanceService workInstanceService;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void addRecords(String instanceId ,String userId) {
        WorkInstanceBo workInstanceById = workInstanceService.getWorkInstanceById(instanceId);
        WorkRecords workRecords1 = new WorkRecords();
            workRecords1.setInstanceId(instanceId);
        if (workInstanceById == null){
            workRecords1.setInstTaskFamily("");
            workRecords1.setInstTaskRevision(0);
        }else {
            workRecords1.setInstTaskFamily(workInstanceById.getInstTaskFamily());
            workRecords1.setInstTaskRevision(workInstanceById.getInstTaskRevision());
        }
            workRecords1.setPid(SnowFlakeUtil.nextId().toString());
            workRecords1.setCreateTime(LocalDateTime.now());
            workRecords1.setUpdateTime(LocalDateTime.now());
            workRecords1.setStartTime(LocalDateTime.now());
            workRecords1.setCreatorId(userId);
            workRecords1.setEditorId(userId);
        save(workRecords1);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateRecords(String userId) {
        List<WorkRecords> list = this.lambdaQuery().
         //   in(WorkRecords::getInstanceId, instanceId).
            eq(WorkRecords::getCreatorId,userId).
            isNull(WorkRecords::getEndTime)
            .isNull(WorkRecords::getCostTimeBySeconds)
            .list();

        // 获取用户docker回收时间
        UserRightsBO userRightsByUser = userRightsService.getUserRightsByUser(userId);
        Optional<UserRightsBO> userRights = Optional.ofNullable(userRightsByUser);
        BigDecimal recoveryTime = UnitConvertUtils.convertDatetime(userRights.map(UserRightsBO::getDockerRecycleDuration).orElse("2H"), TimeUnitEnum.SECOND);

        list.forEach(workRecords -> {
                    workRecords.setEndTime(LocalDateTime.now());
                    workRecords.setUpdateTime(LocalDateTime.now());
                    workRecords.setEditorId(userId);
                    long between = LocalDateTimeUtil.between(workRecords.getStartTime(),LocalDateTime.now(), ChronoUnit.SECONDS);
                    if(between > recoveryTime.longValue()) {
                        // 开启时间超过回收时间则按回收时间记录
                        workRecords.setCostTimeBySeconds(recoveryTime);
                    } else {
                        workRecords.setCostTimeBySeconds(new BigDecimal(between));
                    }
        });
        updateBatchById(list);

    }


    public static void main(String[] args) {
        System.out.println(UnitConvertUtils.convertDatetime("2H", TimeUnitEnum.SECOND));
    }

    @Override
    public String findPidByInstId(String id) {
        List<WorkRecords> list = this.lambdaQuery().eq(WorkRecords::getInstanceId, id).list();
        if (CollectionUtils.isEmpty(list)){
            throw new RuntimeException("请传入实例id");
        }
        return list.get(0).getPid();
    }

    @Override
    public IPage<WorkRecordsBo> findInstanceUsedHistory(PageParam pageParam,String userId) {
        Page<WorkRecords> page = this.page(pageParam.convert(), lambdaQuery()
            .eq(WorkRecords::getCreatorId, userId)
            .orderByDesc(WorkRecords::getCreateTime));

        List<WorkRecords> records = page.getRecords();
        Page<WorkRecordsBo> workRecordsBoPage = new Page<>();
        List<WorkRecordsBo> workRecordsBos = MapperUtil.nf().mapAsList(records, WorkRecordsBo.class);
        workRecordsBoPage.setRecords(workRecordsBos);
        workRecordsBoPage.setCurrent(page.getCurrent());
        workRecordsBoPage.setTotal(page.getTotal());
        workRecordsBoPage.setPages(page.getPages());
        workRecordsBoPage.setOptimizeCountSql(page.isOptimizeCountSql());
        workRecordsBoPage.setSize(page.getSize());
        workRecordsBoPage.setOrders(page.getOrders());
        return workRecordsBoPage;
    }

    @Override
    public Map<String, BigDecimal> findAllAWSHistoryByUserId(String userId) {
        List<WorkRecords> list = this.lambdaQuery().eq(WorkRecords::getCreatorId, userId).list();
        ArrayList<BigDecimal> bigDecimals = new ArrayList<>();
        list.forEach(workRecords -> {
            if (workRecords.getCostTimeBySeconds() != null){
                bigDecimals.add(workRecords.getCostTimeBySeconds());
            }else {
                bigDecimals.add(BigDecimal.ZERO);
            }
        });
        BigDecimal reduce = bigDecimals.stream().reduce(BigDecimal.ZERO, BigDecimal::add);
        HashMap<String, BigDecimal> stringBigDecimalHashMap = new HashMap<>();
        stringBigDecimalHashMap.put(userId,reduce);
        return stringBigDecimalHashMap;
    }


    @Override
    public Boolean ifOverTime(String userId){
        UserRightsBO userRightsByUser = rightsService.getUserRightsByUser(userId);
        Double awsCoreTime = userRightsByUser.getAwsCoreTime();
        BigDecimal multiply = new BigDecimal("3600").multiply(new BigDecimal(awsCoreTime));
        Map<String, BigDecimal> allAWSHistoryByInstId = findAllAWSHistoryByUserId(userId);
        BigDecimal subtract = multiply.subtract(allAWSHistoryByInstId.get(userId));
        if (subtract.compareTo(BigDecimal.ZERO) > 0){
            return true;
        }
        return false;
    }

}
